/**
 * 
 */
package com.ihg.hiex.admin.entity.security;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;

import com.ihg.hiex.entity.user.Account;
import com.ihg.hiex.entity.user.Administrator;
import com.ihg.hiex.entity.user.Role;
import com.ihg.hiex.entity.user.Supervisor;



/**
 * @author Ysy
 */
public class Login implements UserDetails {

    private static final long serialVersionUID = -2977758312542405134L;

    private Long id;
    
    private String name;
    
    private String email;
    
    private String mobile;
    
    private String password;
    
    private String authority;
    
    private Map<String, Set<String>> resources;
    
    /**
     * The default constructor
     */
    public Login() {
    }
    
    /**
     * @param account
     * @param administrator
     */
    public Login(Account account, Administrator administrator) {
        this.id = administrator.getId();
        this.name = administrator.getName();
        this.email = administrator.getEmail();
        this.password = account.getPassword();
        this.mobile = account.getMobile();
    }
    
    /**
     * @param account
     * @param supervisor
     */
    public Login(Account account, Supervisor supervisor) {
        this.id = supervisor.getId();
        this.name = supervisor.getName();
        this.email = supervisor.getEmail();
        this.password = account.getPassword();
        this.mobile = account.getMobile();
    }
    
    public Login(Account account) {
        this.id = account.getId();
        this.name = account.getEmail();
        this.email = account.getEmail();
        this.password = account.getPassword();
        this.mobile = account.getMobile();
    }
    
    /**
     * 
     * @param authority
     * @return
     */
    public Login init(String authority) {
        this.authority = authority;
        this.resources = new HashMap<String, Set<String>>();
        return this;
    }
    
    /**
     * 
     * @return
     */
    public String getAuthorityAlias() {
        return StringUtils.lowerCase(this.authority);
    }
    
    /**
     * 
     * @return
     */
    public boolean isSupervisor() {
        return StringUtils.equalsIgnoreCase(authority, Role.SUPERVISOR.name());
     }
    
    /**
     * 
     * @return
     */
    public boolean isAdministrator() {
    	return StringUtils.equalsIgnoreCase(authority, Role.ADMIN.name());
    }
    
    /**
     * 
     * @return
     */
    public boolean isFacilitator() {
        return StringUtils.equalsIgnoreCase(authority, Role.FACILITATOR.name());
    }
    
    /**
     * 
     * @return
     */
    public boolean isCoach() {
        return StringUtils.equalsIgnoreCase(authority, Role.COACH.name());
    }
    
    /**
     * Initialize resources
     * 
     * @param resources
     */
    public void initResources(Map<String, List<String>> resources) {
        
        for(Iterator<Map.Entry<String, List<String>>> iterator = resources.entrySet().iterator(); iterator.hasNext();) {
            Map.Entry<String, List<String>> entry = iterator.next();
            String key =entry.getKey();
            List<String> values = entry.getValue();
            this.addResource(key, values);
        }

    }
    
    /**
     * Add resource from key and value
     * 
     * @param key
     * @param values
     */
    public void addResource(String key, List<String> values) {
        if(this.resources != null && this.resources.containsKey(key)) {
            this.resources.get(key).addAll(values);
        } else {
            this.resources.put(key, new LinkedHashSet<String>(values));
        }
    }
    
    /**
     * Get resource from key
     * 
     * @param key
     * @return
     */
    public Set<String> getResource(String key) {
        return this.resources.get(key);
    }

    /**
     * 
     * @param type
     * @param key
     * @return
     */
    public boolean hasResource(String type, String key) {
        return this.resources.containsKey(type) && this.resources.get(type).contains(key);
    }
    
    /**
     * 
     * @param roles
     * @return
     */
    public boolean hasAnyPrincipalRole(String... roles) {
        
        Set<String> roleSet = AuthorityUtils.authorityListToSet(this.getAuthorities());

        for (String role : roles) {
            if (roleSet.contains(role)) {
                return true;
            }
        }
        
        return false;
    }

    /* (non-Javadoc)
     * @see org.springframework.security.core.userdetails.UserDetails#getAuthorities()
     */
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return AuthorityUtils.commaSeparatedStringToAuthorityList(this.authority);
    }

    /* (non-Javadoc)
     * @see org.springframework.security.core.userdetails.UserDetails#getPassword()
     */
    public String getPassword() {
        return this.password;
    }

    /* (non-Javadoc)
     * @see org.springframework.security.core.userdetails.UserDetails#getUsername()
     */
    public String getUsername() {
        return this.email;
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.security.core.userdetails.UserDetails#isAccountNonExpired()
     */
    public boolean isAccountNonExpired() {
        return true;
    }

    /* (non-Javadoc)
     * @see org.springframework.security.core.userdetails.UserDetails#isAccountNonLocked()
     */
    public boolean isAccountNonLocked() {
        return true;
    }

    /* (non-Javadoc)
     * @see org.springframework.security.core.userdetails.UserDetails#isCredentialsNonExpired()
     */
    public boolean isCredentialsNonExpired() {
        return true;
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.security.core.userdetails.UserDetails#isEnabled()
     */
    public boolean isEnabled() {
        return true;
    }

    /**
     * @return the id
     */
    public Long getId() {
        return id;
    }
    
    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @return the email
     */
    public String getEmail() {
        return email;
    }

    /**
     * @return the mobile
     */
    public String getMobile() {
        return mobile;
    }

    /**
     * @return the authority
     */
    public String getAuthority() {
        return authority;
    }

    /**
     * @return the resources
     */
    public Map<String, Set<String>> getResources() {
        return resources;
    }

    /**
     * @param id the id to set
     */
    public void setId(Long id) {
        this.id = id;
    }
    
    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @param email the email to set
     */
    public void setEmail(String email) {
        this.email = email;
    }

    /**
     * @param mobile the mobile to set
     */
    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    /**
     * @param password the password to set
     */
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * @param authority the authority to set
     */
    public void setAuthority(String authority) {
        this.authority = authority;
    }

    /**
     * @param resources the resources to set
     */
    public void setResources(Map<String, Set<String>> resources) {
        this.resources = resources;
    }
}
